Safariで「Can't find variable」のエラーが出る場合の対処方法
https://scrapbox.io/files/64f60b047ade73001ceb1f73.png
Babylon.js Playground で作ったプログラムについて、Chrome では動作するのに Safari (iPhone や iPad)でエラーになることがあります。
Babylon.js Playground では実行時に動的に script タグを挿入しコードを実行する仕組みなのですが、Chrome と Safari でスコープの扱いが微妙に異なることが原因のようです。
いくつか対応案がありますが、簡単な解決策としては、変数を var にする方法のようです。
code:js
//const SCALE = 1 / 10; // NG : "Can't find variable: SCALE" error in Safari
var SCALE = 1 / 10; // OK
const createScene = function () {
const scene = new BABYLON.Scene(engine);
const camera = new BABYLON.FreeCamera("camera1", new BABYLON.Vector3(0, 5, -10), scene);
camera.setTarget(BABYLON.Vector3.Zero());
camera.attachControl(canvas, true);
const light = new BABYLON.HemisphericLight("light", new BABYLON.Vector3(0, 1, 0), scene);
light.intensity = 0.7;
const sphere = BABYLON.MeshBuilder.CreateSphere(
"sphere",
{ diameter: 2, segments: 32 },
scene
);
sphere.position.y = 1;
addGround(scene);
return scene;
};
function addGround(scene) {
// "Can't find variable: SCALE" error in Safari
const ground = BABYLON.MeshBuilder.CreateGround(
"ground",
{ width: 60 * SCALE, height: 60 * SCALE },
scene
);
}
以下は、Babylon.js Playground のスクリプトタグの挿入処理がどのようなものかを簡易的に表したコードになります。
code:javascript
let code = `const SCALE = 1 / 10; // TODO: "Can't find variable: SCALE" error in Safari
const createScene = function() {
console.log("createScene()");
addGround();
};
function addGround() {
console.log("addGround()");
// "Can't find variable: SCALE" error in Safari
console.log("width:" + 60 * SCALE);
}
window.initFunction = async function() {
window.scene = createScene();
}
`;
function FastEval(code) {
const head = document.getElementsByTagName("head")0; const script = document.createElement("script");
script.setAttribute("type", "text/javascript");
script.innerHTML = `try {${code};}
catch(e) {
console.log(e);
}`; // Error in Safari
//script.innerHTML = {${code};}; // Error in Safari
//script.innerHTML = ${code};; // No Errors in Safari
head.appendChild(script);
}
async function init() {
FastEval(code);
window.initFunction();
}
init();